home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / 92052tar.gz / 920528.tar / mail_daemn.c < prev    next >
C/C++ Source or Header  |  1992-05-14  |  9KB  |  319 lines

  1. /* @(#) $Header: mail_daemn.c,v 1.10 92/05/14 13:20:16 deyke Exp $ */
  2.  
  3. /* Mail Daemon, checks for outbound mail and starts mail delivery agents */
  4.  
  5. #include <sys/types.h>
  6.  
  7. #include <ctype.h>
  8. #include <dirent.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <sys/stat.h>
  13.  
  14. #include "global.h"
  15. #include "timer.h"
  16. #include "mail.h"
  17. #include "cmdparse.h"
  18. #include "commands.h"
  19.  
  20. static int  Maxclients = 10;
  21. static struct mailsys *Systems;
  22. static struct timer Mail_timer;
  23.  
  24. static int domail_maxcli __ARGS((int argc, char *argv [], void *p));
  25. static int domail_list __ARGS((int argc, char *argv [], void *p));
  26. static int domail_timer __ARGS((int argc, char *argv [], void *p));
  27. static int domail_kick __ARGS((int argc, char *argv [], void *p));
  28. static void strtrim __ARGS((char *s));
  29. static void read_configuration __ARGS((void));
  30. static void mail_tick __ARGS((char *sysname));
  31.  
  32. /*---------------------------------------------------------------------------*/
  33.  
  34. static struct mailers Mailers[] = {
  35.     "bbs",          mail_bbs,
  36.     "smtp",         mail_smtp,
  37.     NULLCHAR
  38. };
  39.  
  40. /*---------------------------------------------------------------------------*/
  41.  
  42. static struct cmds Mail_cmds[] = {
  43. /*      "gateway",      dogateway,      0,      0,      NULLCHAR,           */
  44. /*      "mode",         setsmtpmode,    0,      0,      NULLCHAR,           */
  45.     "kick",         domail_kick,    0,      0,      NULLCHAR,
  46. /*      "kill",         dosmtpkill,     0,      2,      "kill <jobnumber>", */
  47.     "list",         domail_list,    0,      0,      NULLCHAR,
  48.     "maxclients",   domail_maxcli,  0,      0,      NULLCHAR,
  49.     "timer",        domail_timer,   0,      0,      NULLCHAR,
  50. #ifdef SMTPTRACE
  51. /*      "trace",        dosmtptrace,    0,      0,      NULLCHAR,           */
  52. #endif
  53.     NULLCHAR,
  54. };
  55.  
  56. int  dosmtp(argc, argv, p)
  57. int  argc;
  58. char  *argv[];
  59. void *p;
  60. {
  61.   read_configuration();
  62.   return subcmd(Mail_cmds, argc, argv, p);
  63. }
  64.  
  65. /*---------------------------------------------------------------------------*/
  66.  
  67. static int domail_maxcli(argc, argv, p)
  68. int  argc;
  69. char  *argv[];
  70. void *p;
  71. {
  72.   return setint(&Maxclients, "Max clients", argc, argv);
  73. }
  74.  
  75. /*---------------------------------------------------------------------------*/
  76.  
  77. static int  domail_list(argc, argv, p)
  78. int  argc;
  79. char  *argv[];
  80. void *p;
  81. {
  82.  
  83.   char  *state;
  84.   char  waittime[16];
  85.   struct mailsys *sp;
  86.  
  87.   printf("System     Mailer  Transport  State    Wait time\n");
  88.   for (sp = Systems; sp; sp = sp->next) {
  89.     *waittime = '\0';
  90.     switch (sp->state) {
  91.     case MS_NEVER:
  92.       state = "";
  93.       break;
  94.     case MS_SUCCESS:
  95.       state = "Success";
  96.       break;
  97.     case MS_FAILURE:
  98.       state = "Failure";
  99.       if (sp->nexttime > secclock())
  100.     sprintf(waittime, "%d sec", sp->nexttime - secclock());
  101.       break;
  102.     case MS_TRYING:
  103.       state = "Trying";
  104.       break;
  105.     case MS_TALKING:
  106.       state = "Talking";
  107.       break;
  108.     }
  109.     printf("%-10s %-7s %-10s %-8s %9s\n", sp->sysname, sp->mailer->name, sp->protocol, state, waittime);
  110.   }
  111.   return 0;
  112. }
  113.  
  114. /*---------------------------------------------------------------------------*/
  115.  
  116. /* Set outbound spool scan interval */
  117.  
  118. static int  domail_timer(argc, argv, p)
  119. int  argc;
  120. char  *argv[];
  121. void *p;
  122. {
  123.   if (argc < 2) {
  124.     printf("%lu/%lu\n",
  125.         read_timer(&Mail_timer) / 1000,
  126.         dur_timer(&Mail_timer) / 1000);
  127.     return 0;
  128.   }
  129.   Mail_timer.func = (void (*)()) mail_tick;
  130.   Mail_timer.arg = 0;
  131.   set_timer(&Mail_timer, atol(argv[1]) * 1000L);
  132.   start_timer(&Mail_timer);
  133.   return 0;
  134. }
  135.  
  136. /*---------------------------------------------------------------------------*/
  137.  
  138. static int  domail_kick(argc, argv, p)
  139. int  argc;
  140. char  *argv[];
  141. void *p;
  142. {
  143.   mail_tick((argc < 2) ? NULLCHAR : argv[1]);
  144.   return 0;
  145. }
  146.  
  147. /*---------------------------------------------------------------------------*/
  148.  
  149. static void strtrim(s)
  150. char  *s;
  151. {
  152.   char  *p = s;
  153.  
  154.   while (*p) p++;
  155.   while (--p >= s && isspace(uchar(*p))) ;
  156.   p[1] = '\0';
  157. }
  158.  
  159. /*---------------------------------------------------------------------------*/
  160.  
  161. static void read_configuration()
  162. {
  163.  
  164.   FILE * fp;
  165.   char  *sysname, *mailername, *protocol, *address;
  166.   char  line[1024];
  167.   static long  lastmtime;
  168.   struct mailers *mailer;
  169.   struct mailsys *sp;
  170.   struct stat statbuf;
  171.  
  172.   for (sp = Systems; sp; sp = sp->next)
  173.     if (sp->state >= MS_TRYING) return;
  174.   if (stat(CONFFILE, &statbuf)) return;
  175.   if (lastmtime == statbuf.st_mtime || statbuf.st_mtime > secclock() - 5) return;
  176.   if (!(fp = fopen(CONFFILE, "r"))) return;
  177.   while (sp = Systems) {
  178.     Systems = Systems->next;
  179.     free(sp->sysname);
  180.     free(sp->protocol);
  181.     free(sp->address);
  182.     free(sp);
  183.   }
  184.   while (fgets(line, sizeof(line), fp)) {
  185.     if (!(sysname = strtok(line, ":"))) continue;
  186.     if (!(mailername = strtok(NULLCHAR, ":"))) continue;
  187.     if (!(protocol = strtok(NULLCHAR, ":"))) continue;
  188.     if (!(address = strtok(NULLCHAR, ":"))) continue;
  189.     strtrim(address);
  190.     for (mailer = Mailers; mailer->name; mailer++)
  191.       if (!strcmp(mailer->name, mailername)) break;
  192.     if (!mailer->name) continue;
  193.     sp = calloc(1, sizeof(*sp));
  194.     sp->sysname = strdup(sysname);
  195.     sp->mailer = mailer;
  196.     sp->protocol = strdup(protocol);
  197.     sp->address = strdup(address);
  198.     sp->next = Systems;
  199.     Systems = sp;
  200.   }
  201.   fclose(fp);
  202.   lastmtime = statbuf.st_mtime;
  203. }
  204.  
  205. /*---------------------------------------------------------------------------*/
  206.  
  207. static void mail_tick(sysname)
  208. char  *sysname;
  209. {
  210.  
  211.   DIR * dirp;
  212.   FILE * fp;
  213.   char  line[1024];
  214.   char  spooldir[80];
  215.   char  tmp1[1024];
  216.   char  tmp2[1024];
  217.   int  clients;
  218.   int  cnt;
  219.   struct dirent *dp;
  220.   struct mailjob mj, *jp, *tail;
  221.   struct mailsys *sp;
  222.   struct stat statbuf;
  223.  
  224.   struct filelist {
  225.     struct filelist *next;
  226.     char  name[16];
  227.   } *filelist, *p, *q;
  228.  
  229.   start_timer(&Mail_timer);
  230.   read_configuration();
  231.  
  232.   for (clients = 0, sp = Systems; sp; sp = sp->next)
  233.     if (sp->state >= MS_TRYING) clients++;
  234.   for (sp = Systems; sp && clients < Maxclients; sp = sp->next) {
  235.     if (sysname && !strcmp(sp->sysname, sysname)) sp->nexttime = 0;
  236.     if (sp->state >= MS_TRYING || sp->nexttime > secclock()) continue;
  237.     sprintf(spooldir, "%s/%s", SPOOLDIR, sp->sysname);
  238.     if (!(dirp = opendir(spooldir))) continue;
  239.     filelist = 0;
  240.     cnt = 0;
  241.     for (dp = readdir(dirp); dp; dp = readdir(dirp)) {
  242.       if (*dp->d_name != 'C') continue;
  243.       p = malloc(sizeof(*p));
  244.       strcpy(p->name, dp->d_name);
  245.       if (!filelist || strcmp(p->name, filelist->name) < 0) {
  246.     p->next = filelist;
  247.     filelist = p;
  248.       } else {
  249.     for (q = filelist; q->next && strcmp(p->name, q->next->name) > 0; q = q->next) ;
  250.     p->next = q->next;
  251.     q->next = p;
  252.       }
  253.       if (++cnt > MAXJOBS) {
  254.     for (p = filelist; p->next; q = p, p = p->next) ;
  255.     q->next = 0;
  256.     free(p);
  257.     cnt--;
  258.       }
  259.     }
  260.     closedir(dirp);
  261.     tail = 0;
  262.     for (; p = filelist; filelist = p->next, free(p)) {
  263.       memset(&mj, 0, sizeof(mj));
  264.       sprintf(mj.cfile, "%s/%s", spooldir, p->name);
  265.       if (!(fp = fopen(mj.cfile, "r"))) continue;
  266.       while (fgets(line, sizeof(line), fp)) {
  267.     if (*line == 'S' && sscanf(line, "%*s %*s %s %*s %*s %s", tmp1, tmp2) == 2 && *tmp1 == 'D')
  268.       sprintf(mj.dfile, "%s/%s", spooldir, tmp2);
  269.     if (*line == 'S' && sscanf(line, "%*s %*s %s %*s %*s %s", tmp1, tmp2) == 2 && *tmp1 == 'X')
  270.       sprintf(mj.xfile, "%s/%s", spooldir, tmp2);
  271.       }
  272.       fclose(fp);
  273.       if (*mj.dfile == '\0' || *mj.xfile == '\0') continue;
  274.       if (!(fp = fopen(mj.xfile, "r"))) continue;
  275.       while (fgets(line, sizeof(line), fp))
  276.     if (!strncmp(line, "C rmail ", 8)) {
  277.       sprintf(mj.to, "%s!%s", sp->sysname, line + 8);
  278.       strtrim(mj.to);
  279.       break;
  280.     }
  281.       fclose(fp);
  282.       if (!*mj.to) continue;
  283.       if (!(fp = fopen(mj.dfile, "r"))) continue;
  284.       if (fscanf(fp, "%*s %s", tmp1) == 1) {
  285.     if (!strcmp(tmp1, "MAILER-DAEMON")) strcpy(tmp1, Hostname);
  286.     sprintf(mj.from, "%s!%s", Hostname, tmp1);
  287.     strtrim(mj.from);
  288.     while (fgets(line, sizeof(line), fp))
  289.       if (!strncmp(line, "Subject: ", 9)) {
  290.         strcpy(mj.subject, line + 9);
  291.         strtrim(mj.subject);
  292.         break;
  293.       }
  294.       }
  295.       fclose(fp);
  296.       if (!*mj.from) continue;
  297.       if (stat(mj.cfile, &statbuf)) continue;
  298.       if (statbuf.st_mtime + RETURNTIME < secclock()) {
  299.     sprintf(mj.return_reason, "520 %s... Cannot connect for %d days\n", sp->sysname, RETURNTIME / (60L*60*24));
  300.     mail_return(&mj);
  301.       } else {
  302.     jp = malloc(sizeof(*jp));
  303.     *jp = mj;
  304.     if (!sp->jobs)
  305.       sp->jobs = jp;
  306.     else
  307.       tail->next = jp;
  308.     tail = jp;
  309.       }
  310.     }
  311.     if (sp->jobs) {
  312.       sp->state = MS_TRYING;
  313.       clients++;
  314.       (*sp->mailer->func)(sp);
  315.     }
  316.   }
  317. }
  318.  
  319.